package utstat;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import utstat.listeners.Player;

public class Balancx0r {
	


	public Map<String,Object> balance(Collection<Player> players) {
		List<Player> blueTeam = new ArrayList<Player>();
		List<Player> redTeam = new ArrayList<Player>();
		Map<String,Object> result = new HashMap<String,Object>();
		for (Player p : players){
			switch (p.getTeam()) {
			case blue: blueTeam.add(p); break;
			case red: redTeam.add(p);}}
		if(blueTeam.size()<1&&redTeam.size()<1) return null;
		
		Swap swap2 = getBest2PlayerSwap(blueTeam, redTeam);
		doSwap(blueTeam, redTeam, swap2);
		int balance = getBalance(redTeam,blueTeam);
		int redTimeOffset = getRedTimeIncrease(balance);
		
		result.put("swap", swap2);
		result.put("balance", Math.abs(balance));
		result.put("redTimeOffset", redTimeOffset);
		
		return result;
	/*	System.out.println("before: red:"+getTotalScore(redTeam)+" blue"+getTotalScore(blueTeam)+" diff:"+getScoreDifference(redTeam,blueTeam)+" balance:"+Math.abs(getBalance(redTeam,blueTeam))+"%");

		System.out.println(swap2);
		
		System.out.println(
				"after: red:"+getTotalScore(redTeam)
				+" blue:"+getTotalScore(blueTeam)
				+" diff:"+getScoreDifference(redTeam,blueTeam)
				+" balance:"+Math.abs(balance)+"%"+
				" red time increase:"+getRedTimeIncrease(balance));*/
	
	}
	
	
	public int getRedTimeIncrease(int balance) {
		int absBalance = Math.abs(balance);
		int imbalance = 100-absBalance;
		imbalance/=10;
		return balance>0?imbalance:-imbalance;
	} 
	


	private int getBalance(List<Player> redTeam, List<Player> blueTeam) {
		int blueScore = getTotalScore(blueTeam);
		int redScore  = getTotalScore(redTeam);
		double maxScore = Math.max(redScore, blueScore);
		double minScore = Math.min(redScore, blueScore);
		
		int balance = (int)Math.round(minScore / maxScore*100);
		return (redScore>blueScore)?balance:-balance;
	}

	public int getTotalScore(List<Player> team) {
		int score = 0;
		for(Player p : team) score+=p.getScore();
		return score;
	}
	
	public int getScoreDifference(List<Player> red, List<Player> blue) {
		return getTotalScore(red)-getTotalScore(blue);
	}
	
	public Swap getBest2PlayerSwap(List<Player> blue,List<Player> red) {
		
		final int idealSwapValue = getScoreDifference(red,blue)/2;
		
		Set<Swap> allSwaps = new TreeSet<Swap>(new Comparator<Swap>() {
			@Override
			public int compare(Swap s1, Swap s2) {
				if (Math.abs(s1.getScoreOffset() - idealSwapValue) < Math.abs(s2.getScoreOffset() - idealSwapValue)) return -1;
				return 1;
			}
		});
		
		allSwaps.add(new Swap(null,null)); // no change, might be the best option

		for (Player b : blue)
			for (Player r : red)
				allSwaps.add(new Swap(b, r));
		
		for (Player b : blue)
			allSwaps.add(new Swap(b, null));
			for (Player r : red)
				allSwaps.add(new Swap(null, r));
		
		/*System.out.println("----------2 swaps");
		System.out.println("ideal2SwapValue = "+idealSwapValue);
		for(Swap s : allSwaps) {
			System.out.println(s);
		}*/
		return allSwaps.iterator().next();
	}
	


	public void doSwap(List<Player> blueTeam, List<Player> redTeam, Swap swap) {
		if (swap.getBluePlayer() != null) {
			blueTeam.remove(swap.getBluePlayer());
			redTeam.add(swap.getBluePlayer());
		}
		if (swap.getRedPlayer() != null) {
			redTeam.remove(swap.getRedPlayer());
			blueTeam.add(swap.getRedPlayer());

		}
	}

}
